{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "from faker import Faker\n",
    "from faker.providers import BaseProvider\n",
    "import random\n",
    "import time\n",
    "import datetime\n",
    "import chinese_calendar\n",
    "import threading\n",
    "import pymysql\n",
    "from threading import Thread\n",
    "from time import sleep,ctime\n",
    "import itertools\n",
    "import calendar\n",
    "import pandas as pd\n",
    "import numpy as np"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "#自定义faker数据生成\n",
    "\n",
    "fake = Faker(locale='zh_CN') # 可生成中文数据\n",
    "\n",
    "station_time={\n",
    "    'line1':(1, 4, 3, 2, 2, 2, 2 ,2 ,3 ,2 ,2 ,2 ,2 ,3 ,2 ,1 ,2 ,2 ,3 ,3 ,2 ,3 ,1),\n",
    "    'line2':(1 ,2 ,2 ,3 ,1 ,3 ,2 ,2 ,2 ,3 ,2 ,2 ,3 ,1 ,3 ,3 ,2 ,2 ,4 ,2 ,1 ,2 ,2 ,2 ,2 ,2 ,1),\n",
    "    'line3':(1 ,3 ,2 ,3 ,3 ,2 ,3 ,2 ,2 ,3 ,2 ,2 ,2 ,3 ,2 ,2 ,3 ,3 ,2 ,2 ,1),\n",
    "    'line4':(1 ,3 ,2 ,3 ,3 ,3 ,2 ,4 ,3 ,3 ,2 ,2 ,2 ,2 ,3 ,2 ,2 ,2 ,2 ,3 ,2 ,2 ,3 ,3 ,2 ,3 ,2 ,2)\n",
    "}\n",
    "lines={\n",
    "    'line1':('双港','孔目湖','长江路','珠江路','庐山南大道','绿茵路','卫东','地铁大厦','秋水广场','滕王阁','万寿宫','八一馆','八一广场',\n",
    "           '丁公路北','师大南路','彭家桥','谢家村','青山湖大道','高新大道','艾溪湖西','艾溪湖东','太子殿','奥体中心','瑶湖西'),\n",
    "    'line2':('南路','大岗','生米','九龙湖南','市民中心','鹰潭街','国博','西站南广场','南昌西站','龙岗','国体中心','卧龙山','岭北','前湖大道','学府大道东','翠苑路',\n",
    "           '地铁大厦','雅苑路','红谷中大道','阳明公园','青山路口','福州路','八一广场','永叔路','丁公路南','南昌火车站','顺外','辛家庵'),\n",
    "    'line3':('银三角北','斗门','柏岗','沥山','振兴大道','邓埠','八大山人','施尧','江铃','京家山','十字街','绳金塔','六眼井','八一馆','墩子塘','青山路口',\n",
    "           '上沙沟','青山湖西','国威路','火炬广场','梁万','京东大道'),\n",
    "    'line4':('白马山','裕丰街','璜溪','中堡','礼庄山','西站南广场','怀玉山大道','安丰','东新','新洪城大市场','丁家洲','观洲','云天路','灌婴路','南昌大桥东','桃苑',\n",
    "           '绳金塔','坛子口','丁公路南','丁公路北','人民公园','上沙沟','起凤路','七里','民园路西','火炬','北沥','科技城','鱼尾洲')\n",
    "}\n",
    "stations=tuple(set(lines['line1']+lines['line2']+lines['line3']+lines['line4']))\n",
    "\n",
    "#付款方式\n",
    "payment_method=('码','一卡通','地铁票')\n",
    "\n",
    "#天气\n",
    "weathers=('晴','阴','雨')\n",
    "\n",
    "\n",
    "\n",
    "class MyProvider(BaseProvider):\n",
    "\n",
    "    #年龄\n",
    "    def my_age(self):\n",
    "        self.age = random.randint(10,70)\n",
    "        return self.age\n",
    "    \n",
    "    #入站站点\n",
    "    def my_enterstation(self):\n",
    "        self.enterstation = random.choice(stations)\n",
    "        return self.enterstation\n",
    "    \n",
    "    #出站站点\n",
    "    def my_outstation(self):\n",
    "        self.outstation = random.choice(stations)\n",
    "        return self.outstation\n",
    "    \n",
    "    #付款方式\n",
    "    def my_payment(self):\n",
    "        self.payment = random.choice(payment_method)\n",
    "        return self.payment\n",
    "    \n",
    "    #天气\n",
    "    def my_weather(self):\n",
    "        self.weather = random.choice(weathers)\n",
    "        return self.weather\n",
    "    \n",
    "\n",
    "fake.add_provider(MyProvider)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "def build_subway(lines,station_time):\n",
    "    \"\"\"\n",
    "    Input is build_subway(linename='station1 station2...'...)\n",
    "    Ouput is a dictionary like {station:{neighbor1:line number,neighbor2:line number,...},station2:{...},...}\n",
    "    \"\"\"\n",
    "\n",
    "    stations = set()\n",
    "    for key in lines.keys():\n",
    "        stations.update(set(lines[key]))\n",
    "    system = {}\n",
    "    for station in stations:\n",
    "        next_station = {}\n",
    "        for key in lines: \n",
    "            if station in lines[key]:\n",
    "                line = lines[key]\n",
    "                idx = line.index(station)\n",
    "                if idx == 0:\n",
    "                    next_station[line[1]] = (station_time[key][0],key)\n",
    "                elif idx == len(line)-1:\n",
    "                    next_station[line[idx-1]]=(station_time[key][idx-1],key)\n",
    "                else:\n",
    "                    next_station[line[idx-1]] = (station_time[key][idx-1],key)\n",
    "                    next_station[line[idx+1]] = (station_time[key][idx],key)\n",
    "        system[station] = next_station\n",
    "    return system\n",
    "\n",
    "          \n",
    "#消费金额（起步价2元/6站之内，每增加6站加1元）\n",
    "def cal_money(station_num):\n",
    "    if station_num==0:\n",
    "        money=0\n",
    "    elif station_num <=6:\n",
    "        money = 2\n",
    "    else:\n",
    "        money=3+(station_num-7)//6\n",
    "    return money\n",
    "\n",
    "\n",
    "\n",
    "def my_time(sw_time_min):\n",
    "    \n",
    "    #这里设置时间的范围,可设置年，月，日\n",
    "    t_year=2021\n",
    "    t_mouth=random.randint(1,12)\n",
    "    t_day=random.randint(1,calendar.monthrange(t_year,t_mouth)[1])\n",
    "    s = (t_year,t_mouth,t_day,6,0,0,0,0,0) #设置开始日期时间元组（2019-08-01 00：00：00）\n",
    "    e = (t_year,t_mouth,t_day,23,30,0,0,0,0) #设置结束日期时间元组（2019-08-31 23：59：59)\n",
    "   \n",
    "    start = time.mktime(s) #生成开始时间戳\n",
    "    end = time.mktime(e) #生成结束时间戳\n",
    "\n",
    "    entertime = random.randint(start, end) # 在开始和结束时间戳中随机取出一个\n",
    "\n",
    "\n",
    "    date_touple = time.localtime(entertime) # 将时间戳生成时间元组\n",
    "    enter_time = time.strftime(\"%Y-%m-%d %H:%M:%S\", date_touple)\n",
    "    enter_time1=datetime.datetime.strptime(enter_time,\"%Y-%m-%d %H:%M:%S\")#入站时间\n",
    "\n",
    "    # 判断是否是节假日(节假日包括周末和节日)\n",
    "    demo_time=datetime.date(enter_time1.year, enter_time1.month, enter_time1.day)\n",
    "    isholiday = chinese_calendar.is_holiday(demo_time) \n",
    "\n",
    "    #判断该日是星期几\n",
    "    week=enter_time1.weekday() + 1 \n",
    "\n",
    "    exit_time=enter_time1+ datetime.timedelta(minutes=sw_time_min)\n",
    "    exit_time1=enter_time1+ datetime.timedelta(minutes=sw_time_min+15)\n",
    "\n",
    "    exittime=time.mktime(tuple(exit_time.timetuple()[0:9])) \n",
    "    exittime1=time.mktime(tuple(exit_time1.timetuple()[0:9])) \n",
    "\n",
    "    outtime=random.randint(exittime,exittime1)\n",
    "    date_touple1 = time.localtime(outtime) # 将时间戳生成时间元组\n",
    "    out_time = time.strftime(\"%Y-%m-%d %H:%M:%S\", date_touple1)\n",
    "    out_time1=datetime.datetime.strptime(out_time,\"%Y-%m-%d %H:%M:%S\")#出站时间\n",
    "\n",
    "    #计算搭乘时间,入出站乘坐地铁假设有个3分钟\n",
    "    td=out_time1-enter_time1\n",
    "    hours, remainder = divmod(td.seconds, 3600)\n",
    "    minutes, seconds = divmod(remainder, 60)\n",
    "    taketime=minutes+3\n",
    "    \n",
    "    #入站时间是那一天，在什么时间段\n",
    "    enter_time_day=enter_time.split()[0]\n",
    "    enter_time_hour=enter_time.split()[1]\n",
    "    \n",
    "    #出站时间是那一天，在什么时间段\n",
    "    out_time_day=out_time.split()[0]\n",
    "    out_time_hour=out_time.split()[1]\n",
    "    \n",
    "    return enter_time_day,enter_time_hour,out_time_day,out_time_hour,taketime,week,isholiday\n",
    "\n",
    "\n",
    "#南昌地铁Graph\n",
    "nc_subway=build_subway(lines,station_time)\n",
    "\n",
    "def is_line(line):\n",
    "    if line=='line1':\n",
    "        return 1\n",
    "    elif line=='line2':\n",
    "        return 2\n",
    "    elif line=='line3':\n",
    "        return 3\n",
    "    else:\n",
    "        return 4\n",
    "    \n",
    "def is_station_line(enter_station):\n",
    "    for key in lines:\n",
    "        if enter_station in lines[key]:\n",
    "            return key    \n",
    "\n",
    "all_paths=[]\n",
    "for enter_station in stations:\n",
    "    for out_station in stations:\n",
    "        # 求所有路径\n",
    "        def all_path(start, goal, path=[],sw_time=[],change=[]):\n",
    "            if not path:\n",
    "                path.append(start)\n",
    "\n",
    "            if start == goal:\n",
    "                sw_times.append(sw_time[:])\n",
    "                changes_all.append(len([k for k, _ in itertools.groupby(change[:])])-1)\n",
    "                changes.append(change[:])\n",
    "                changes_lines.append([k for k, _ in itertools.groupby(change[:])])\n",
    "                sw_times_all.append(sum(sw_time[:]))\n",
    "                sw_taketimes_all.append(sum(sw_time[:])+(len([k for k, _ in itertools.groupby(change[:])])-1)*5)\n",
    "                paths.append(path[:])\n",
    "                return\n",
    "            for state, action in nc_subway[start].items():\n",
    "                if state not in path:\n",
    "                    sw_time.append(action[0])\n",
    "                    change.append(action[1])\n",
    "                    path.append(state)\n",
    "                    all_path(state, goal)\n",
    "                    change.pop()\n",
    "                    sw_time.pop()\n",
    "                    path.pop()\n",
    "        paths = []#两点之间的全部路径\n",
    "        sw_times=[]#路径经过各站点花费的时间\n",
    "        sw_times_all=[]#每条路径所花费的时间\n",
    "        sw_taketimes_all=[]#每条路径所花费的时间+换乘的总时间\n",
    "        changes=[]#路径经过各站点的地铁线号\n",
    "        changes_lines=[]#路径大致经过了那几条线\n",
    "        changes_all=[]#每条路径换成的次数\n",
    "        \n",
    "\n",
    "        all_path(enter_station, out_station)\n",
    "        path_min = paths[sw_taketimes_all.index(min(sw_taketimes_all))]#花费时间最短路径\n",
    "        change_min_num=changes_all[sw_taketimes_all.index(min(sw_taketimes_all))]#最小换乘次数\n",
    "        changes_min_lines=changes_lines[sw_taketimes_all.index(min(sw_taketimes_all))]#花费时间最短路径经过了几号线\n",
    "        \n",
    "        #\n",
    "        sw_time_min=min(sw_times_all)#最短路径花费的时间\n",
    "        station_num=len(path_min)-1\n",
    "        money=cal_money(station_num)\n",
    "        \n",
    "        if len(changes_min_lines)==0:\n",
    "            in_line=is_station_line(enter_station)\n",
    "            enter_line=is_line(in_line)#入站站口所属于几号线\n",
    "            out_line=is_line(in_line)#出站站口所属于几号线\n",
    "        else:\n",
    "            enter_line=is_line(changes_min_lines[0])#入站站口所属于几号线\n",
    "            out_line=is_line(changes_min_lines[-1])#出站站口所属于几号线        \n",
    "        \n",
    "        two_path=[enter_station,enter_line,out_station,out_line,sw_time_min,money]\n",
    "        all_paths.append(two_path)\n",
    "        \n",
    "columns = ['enter_station','enter_line','out_station','out_line','sw_time_min','money']\n",
    "data = []\n",
    "data.append(columns)\n",
    "data.extend(all_paths)  # 合并列名与数据\n",
    "dataframe = pd.DataFrame(data)\n",
    "dataframe.to_csv('all_paths.csv',encoding='utf-8', index=False, header=0)\n",
    "df= pd.read_csv(\"all_paths.csv\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "def gettime():\n",
    "    '''\n",
    "    :return: 当前时间的规范形式\n",
    "    '''\n",
    "    now_time = datetime.datetime.now().strftime('%Y-%m-%d %H-%M-%S')\n",
    "    return now_time"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "def function(thread_id,num):\n",
    "# def function(num):\n",
    "    '''\n",
    "    \n",
    "    '''\n",
    "    print('---开始---', '线程',thread_id, '时间', ctime())\n",
    "       \n",
    "    datalist = []\n",
    "        \n",
    "#     这里设置你要生成的数据量\n",
    "    for i in range((thread_id-1)*num+1,thread_id*num+1):\n",
    "        \n",
    "        user_id=fake.phone_number()#用户id\n",
    "        enter_station=fake.my_enterstation()#入站站口\n",
    "        out_station=fake.my_outstation()#出站站口\n",
    "        distance=np.array(df[(df.enter_station==enter_station)&(df.out_station==out_station)]).tolist()\n",
    "        sw_time_min=distance[0][4]\n",
    "        money=distance[0][5]\n",
    "        enter_line=distance[0][1]\n",
    "        out_line=distance[0][3]\n",
    "        #入站时间，星期几，是否是节假日\n",
    "        enter_time_day,enter_time_hour,out_time_day,out_time_hour,take_time,week,is_holiday= my_time(sw_time_min)\n",
    "        \n",
    "        order_num=i#订单编号\n",
    "\n",
    "        weather=fake.my_weather()#天气\n",
    "        age=fake.my_age()#年龄\n",
    "        payment=fake.my_payment()#付款方式\n",
    "\n",
    "        datalist.append([order_num,user_id,enter_station,enter_line,enter_time_day,enter_time_hour,out_station,out_line,out_time_day,out_time_hour,take_time,week,is_holiday,weather,age,payment,money])\n",
    "    \n",
    "    outputfile = './' + gettime() + '线程' + str(thread_id) +'.csv'\n",
    "    # 定义列名\n",
    "    \n",
    "    '''\n",
    "    order_num （订单编号）       user_id （用户id）\n",
    "    enter_station （进站站口） ，enter_line （进站站口属于几号线） ，enter_time_day （进站日期）， enter_time_hour （进站时间）\n",
    "    out_station （出站站口）， out_line （出站站口属于几号线） ，out_time_day （出站日期） ，out_time_hour （出站时间）\n",
    "    take_time （搭乘时间） ，week （周几） ，is_holiday （是否是节假日） ，weather （天气） ，age （年龄） ，payment （付款方式 ），money （金额）\n",
    "    '''\n",
    "   \n",
    "    columns = ['order_num','user_id','enter_station','enter_line','enter_time_day','enter_time_hour','out_station','out_line','out_time_day','out_time_hour','take_time','week','is_holiday','weather','age','payment','money']\n",
    "    Data = []\n",
    "    Data.append(columns)\n",
    "    Data.extend(datalist)  # 合并列名与数据\n",
    "    #生成csv数据文件\n",
    "    dataframe = pd.DataFrame(Data)\n",
    "    dataframe.to_csv(outputfile, encoding='utf-8', index=False, header=0)\n",
    "    \n",
    "    print('***结束***', '线程', thread_id, '时间', ctime())\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "def Multithreaded_create_data(thread_num,num):\n",
    "    '''\n",
    "    1、创建线程生成数据\n",
    "    :param datalist: \n",
    "    :return: 实现多线程生成数据\n",
    "    '''\n",
    "    threads=[]\n",
    "    \n",
    "    for i in range(1,thread_num+1):\n",
    "        thread=Thread(target=function(i,num),name='thread{}'.format(i))\n",
    "        thread.start()\n",
    "        threads.append(thread)\n",
    "    \n",
    "    for tt in threads:\n",
    "        tt.join()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "---开始--- 线程 1 时间 Wed Mar  2 20:04:55 2022\n",
      "***结束*** 线程 1 时间 Wed Mar  2 20:28:37 2022\n",
      "---开始--- 线程 2 时间 Wed Mar  2 20:28:38 2022\n",
      "***结束*** 线程 2 时间 Wed Mar  2 20:52:14 2022\n",
      "---开始--- 线程 3 时间 Wed Mar  2 20:52:14 2022\n",
      "***结束*** 线程 3 时间 Wed Mar  2 21:16:52 2022\n",
      "---开始--- 线程 4 时间 Wed Mar  2 21:16:52 2022\n",
      "***结束*** 线程 4 时间 Wed Mar  2 21:42:59 2022\n",
      "---开始--- 线程 5 时间 Wed Mar  2 21:43:00 2022\n",
      "***结束*** 线程 5 时间 Wed Mar  2 22:08:25 2022\n",
      "---开始--- 线程 6 时间 Wed Mar  2 22:08:25 2022\n",
      "***结束*** 线程 6 时间 Wed Mar  2 22:32:17 2022\n",
      "---开始--- 线程 7 时间 Wed Mar  2 22:32:18 2022\n",
      "***结束*** 线程 7 时间 Wed Mar  2 22:56:30 2022\n",
      "---开始--- 线程 8 时间 Wed Mar  2 22:56:30 2022\n",
      "***结束*** 线程 8 时间 Wed Mar  2 23:29:21 2022\n",
      "---开始--- 线程 9 时间 Wed Mar  2 23:29:22 2022\n",
      "***结束*** 线程 9 时间 Thu Mar  3 00:04:50 2022\n",
      "---开始--- 线程 10 时间 Thu Mar  3 00:04:50 2022\n",
      "***结束*** 线程 10 时间 Thu Mar  3 00:39:22 2022\n"
     ]
    }
   ],
   "source": [
    "if __name__ == '__main__':\n",
    "    #第一个参数是创建线程的数量\n",
    "    #第二个参数是每个线程要生成多少数据量\n",
    "    Multithreaded_create_data(10,1000000)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": false
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.8"
  },
  "varInspector": {
   "cols": {
    "lenName": 16,
    "lenType": 16,
    "lenVar": 40
   },
   "kernels_config": {
    "python": {
     "delete_cmd_postfix": "",
     "delete_cmd_prefix": "del ",
     "library": "var_list.py",
     "varRefreshCmd": "print(var_dic_list())"
    },
    "r": {
     "delete_cmd_postfix": ") ",
     "delete_cmd_prefix": "rm(",
     "library": "var_list.r",
     "varRefreshCmd": "cat(var_dic_list()) "
    }
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
